#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#include <unordered_map>
#include <unordered_set>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <deque>
#include <functional>
#include <climits>

#define quickio ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define endl "\n"

using namespace std;
typedef long long ll;

#define lc (p*2)
#define rc (p*2+1)

const int N = 1e5 + 5;

int n, q, m;
int a[N];

struct node
{
	int l;
	int r;
	ll sum;
	ll add;
	ll cheng;
}tr[4 * N];

void pushup(int p)
{
	tr[p].sum = tr[lc].sum + tr[rc].sum;
}

void pushdown(int p)
{
	if (tr[p].add)
	{
		tr[lc].add += tr[p].add;
		tr[rc].add += tr[p].add;
		tr[lc].sum += tr[p].add*(tr[lc].r - tr[lc].l + 1);
		tr[rc].sum += tr[p].add*(tr[rc].r - tr[rc].l + 1);
		tr[p].add = 0;
	}
	if (tr[p].cheng != 1)
	{
		tr[lc].cheng += tr[p].cheng;
		tr[rc].cheng += tr[p].cheng;
		tr[lc].sum *= tr[p].cheng * (tr[lc].r - tr[lc].l + 1);
		tr[rc].sum*= tr[p].cheng * (tr[rc].r - tr[rc].l + 1);
		tr[p].cheng = 1;
	}
}

void change1(int p, int x, int y, int k)
{
	if (tr[p].l >= x && tr[p].r <= y)
	{
		tr[p].sum += k * (tr[p].r - tr[p].l + 1);
		tr[p].add += k;
		pushup(p);
		return;
	}

	int mid = (tr[p].l + tr[p].r) / 2;
	pushdown(p);
	if (x <= mid)
		change1(lc, x, y, k);
	if (y > mid)
		change1(rc, x, y, k);
	pushup(p);
}

void change2(int p, int x, int y, int k)
{
	if (tr[p].l >= x && tr[p].r <= y)
	{
		tr[p].sum *= k * (tr[p].r - tr[p].l + 1);
		tr[p].cheng += k;
		return;
	}

	int mid = (tr[p].l + tr[p].r) / 2;
		pushdown(p);
	if (x <= mid)
		change2(lc, x, y, k);
	if (y > mid)
		change2(rc, x, y, k);
	pushup(p);
}


void bulid(int p, int l, int r)
{
	tr[p] = { l, r, a[l] ,1};
	if (l == r)
		return;

	int mid = (l + r) / 2;
	bulid(lc, l, mid);
	bulid(rc, mid + 1, r);
	pushup(p);
}

ll query(int p, int x, int y)
{
	if (tr[p].l >= x && tr[p].r <= y)
	{
		return tr[p].sum % m;
	}

	int mid = (tr[p].l + tr[p].r) / 2;
	ll sum = 0;
	if (x <= mid)
		sum += query(lc, x, y);
	sum %= m;
	if (y > mid)
		sum += query(rc, x, y);
	sum %= m;
	pushup(p);
	return sum;
}

int main()
{
	cin >> n >> q >> m;
	for (int i = 1; i <= n; i++)
	{
		cin >> a[i];
	}
	bulid(1, 1, n);

	int qq, x, y, k;
	int book;//book = 1:+,  =2:*
	while (q--)
	{
		cin >> qq;
		if (qq == 1 || qq == 2)
		{
			cin >> x >> y >> k;
			if (qq == 2)
			{
				if (k != 0)
				change1(1, x, y, k);
			}
			else
			{
				if (k != 1)
				change2(1, x, y, k);
			}
		}
		else
		{
			cin >> x >> y;
			cout << query(1, x, y) << endl;
		}
	}
	return 0;
}